const { parse } = require('node-html-parser');

/**
 * 创建一个类似 cheerio 的 $ 函数
 * 支持基础伪类选择器：:contains(), :first-child, :last-child, :nth-child(n)
 *
 * @param {string} html - HTML 字符串
 * @returns {Function} $(selector) => { text(), html(), attr(name), length, eq(i) }
 */
function createCheerioLike(html) {
  const root = parse(html);

  function $(selector) {
    let elements = [];

    try {
      // 首先尝试直接使用 node-html-parser 的原生 querySelectorAll 解析选择器
      elements = root.querySelectorAll(selector);
    } catch (e) {
      // 如果原生解析失败，再尝试自定义解析逻辑
      // 处理 :contains(text)
      if (selector.includes(':contains(')) {
        const match = selector.match(/^(.*?):contains\(['"]?(.*?)['"]?\)$/);
        if (match) {
          const baseSelector = match[1].trim() || '*';
          const searchText = match[2];
          let baseElements;

          if (baseSelector === '*') {
            baseElements = [root, ...root.querySelectorAll('*')];
          } else {
            baseElements = root.querySelectorAll(baseSelector);
          }

          elements = baseElements.filter(el => el.textContent.includes(searchText));
        } else {
          // 降级：尝试直接查询（可能语法错误）
          elements = root.querySelectorAll(selector);
        }
      }
      // 处理 :first-child
      else if (/:first-child$/.test(selector)) {
        const baseSelector = selector.replace(/:first-child$/, '').trim();
        const parents = baseSelector === '' ? [root] : root.querySelectorAll(baseSelector);

        elements = parents.map(parent => (parent.children && parent.children.length > 0 ? parent.children[0] : null)).filter(el => el !== null);
      }
      // 处理 :last-child
      else if (/:last-child$/.test(selector)) {
        const baseSelector = selector.replace(/:last-child$/, '').trim();
        const parents = baseSelector === '' ? [root] : root.querySelectorAll(baseSelector);

        elements = parents
          .map(parent => {
            const children = parent.children || [];
            return children.length > 0 ? children[children.length - 1] : null;
          })
          .filter(el => el !== null);
      }
      // 处理 :nth-child(n)
      else if (/:nth-child\(\d+\)$/.test(selector)) {
        const match = selector.match(/^(.*?):nth-child\((\d+)\)$/);
        if (match) {
          const baseSelector = match[1].trim() || '*';
          const index = parseInt(match[2], 10) - 1; // 转为 0-based
          const parents = baseSelector === '*' ? [root] : root.querySelectorAll(baseSelector);

          elements = parents
            .map(parent => {
              const children = parent.children || [];
              return children[index] || null;
            })
            .filter(el => el !== null);
        } else {
          elements = [];
        }
      }
      // 其他选择器
      else {
        console.warn('Failed to parse selector:', selector);
        elements = [];
      }
    }

    // 返回类 cheerio API
    return {
      /**
       * 获取所有匹配元素的文本内容拼接
       */
      text() {
        return elements
          .map(el => el?.textContent || '')
          .join(' ')
          .replace(/\s+/g, ' ')
          .trim();
      },

      /**
       * 获取所有匹配元素的 innerHTML 拼接
       */
      html() {
        return elements.map(el => el?.innerHTML || '').join('');
      },

      /**
       * 获取第一个元素的属性值
       * @param {string} name - 属性名
       */
      attr(name) {
        const el = elements[0];
        return el ? el.getAttribute(name) : undefined;
      },

      /**
       * 匹配的元素数量
       */
      length: elements.length,

      /**
       * 获取指定索引的元素包装对象
       * @param {number} i - 索引
       */
      eq(i) {
        const el = elements[i];
        return {
          text: () => (el?.textContent || '').trim(),
        };
      },
    };
  }

  return $;
}

/**
 * 解析HTML内容并提取数据
 * @param {string} htmlContent - HTML内容
 * @param {Object} mapping - 映射配置 { jobMapping, companyMapping, parseConfig }
 * @param {Object} logger - 日志工具（需支持 debug, info, error, warning）
 * @returns {Object} { jobData, companyData }
 */
function parseHtmlContent(htmlContent, mapping, logger) {
  try {
    // 预处理HTML：压缩空白
    const htmlRaw = htmlContent
      .replace(/\s\s+/g, ' ')
      .replace(/\s*\n\s*/g, '')
      .replace(/\s*\t\s*/g, '')
      .trim();

    // 创建 $ 函数
    const $ = createCheerioLike(htmlRaw);
    logger.debug('DOM结构解析完成');

    // 验证映射配置
    const validatedMapping = validateMapping(mapping);
    logger.debug('映射配置验证通过');

    // 解析岗位数据
    logger.info('开始解析岗位数据');
    const jobData = {};
    let missingRequiredFields = false;

    if (validatedMapping.jobMapping && typeof validatedMapping.jobMapping === 'object') {
      Object.entries(validatedMapping.jobMapping).forEach(([field, rule]) => {
        try {
          let value = null;

          if (rule.selector) {
            const $element = $(rule.selector);
            value = $element.text();

            if (value) {
              if (rule.parser && typeof rule.parser === 'function') {
                value = rule.parser.call(mapping, value);
                logger.debug(`字段 ${field}(${rule.description}) 解析后值: ${value}`);
              } else {
                logger.debug(`字段 ${field}(${rule.description}) 原始值: ${value}`);
              }
              jobData[field] = value;
            } else {
              jobData[field] = validatedMapping.parseConfig.handleMissing(field, rule);
              if (rule.required) {
                logger.error(`岗位必填字段 ${field}(${rule.description}) 值为空`);
                missingRequiredFields = true;
              }
            }
          } else if (rule.default !== undefined) {
            jobData[field] = typeof rule.default === 'function' ? rule.default() : rule.default;
            logger.debug(`字段 ${field}(${rule.description}) 使用默认值: ${jobData[field]}`);
          } else {
            jobData[field] = validatedMapping.parseConfig.handleMissing(field, rule);
            if (rule.required) {
              logger.error(`岗位必填字段 ${field}(${rule.description}) 无选择器且无默认值`);
              missingRequiredFields = true;
            }
          }
        } catch (error) {
          logger.error(`解析岗位字段 ${field}(${rule.description}) 时出错: ${error.message}`);
          jobData[field] = `[解析错误: ${error.message}]`;
        }
      });
    } else {
      logger.debug('未提供岗位映射配置，跳过岗位数据解析');
    }

    // 解析企业数据
    logger.info('开始解析企业数据');
    const companyData = {};

    Object.entries(validatedMapping.companyMapping).forEach(([field, rule]) => {
      try {
        let value = null;

        if (rule.selector) {
          const $element = $(rule.selector);
          value = $element.text();

          if (value) {
            if (rule.parser && typeof rule.parser === 'function') {
              value = rule.parser.call(mapping, value);
              logger.debug(`字段 ${field}(${rule.description}) 解析后值: ${value}`);
            } else {
              logger.debug(`字段 ${field}(${rule.description}) 原始值: ${value}`);
            }
            companyData[field] = value;
          } else {
            companyData[field] = validatedMapping.parseConfig.handleMissing(field, rule);
            if (rule.required) {
              logger.warn(`企业必填字段 ${field}(${rule.description}) 值为空`);
              missingRequiredFields = true;
            }
          }
        } else if (rule.default !== undefined) {
          companyData[field] = typeof rule.default === 'function' ? rule.default() : rule.default;
          logger.debug(`字段 ${field}(${rule.description}) 使用默认值: ${companyData[field]}`);
        } else {
          companyData[field] = validatedMapping.parseConfig.handleMissing(field, rule);
          if (rule.required) {
            logger.warn(`企业必填字段 ${field}(${rule.description}) 无选择器且无默认值`);
            missingRequiredFields = true;
          }
        }
      } catch (error) {
        logger.error(`解析企业字段 ${field}(${rule.description}) 时出错: ${error.message}`);
        companyData[field] = `[解析错误: ${error.message}]`;
      }
    });

    logger.info('HTML数据解析完成');
    if (missingRequiredFields) {
      logger.warn('存在必填字段缺失，请检查日志');
    }

    return { jobData, companyData };
  } catch (error) {
    logger.error(`解析HTML内容时发生未预期错误: ${error.message}`);
    throw new Error(`HTML解析失败: ${error.message}`);
  }
}

/**
 * 验证映射配置的合法性
 * @param {Object} mapping
 * @returns {Object} 验证后的配置
 */
function validateMapping(mapping) {
  if (!mapping || typeof mapping !== 'object') {
    throw new Error('映射配置不能为空且必须是对象');
  }

  // 可选：岗位映射非强制
  if (mapping.jobMapping && typeof mapping.jobMapping !== 'object') {
    throw new Error('岗位映射配置必须是对象');
  }

  if (!mapping.companyMapping || typeof mapping.companyMapping !== 'object') {
    throw new Error('企业映射配置不能为空且必须是对象');
  }

  // 处理缺失字段的默认行为
  if (!mapping.parseConfig || typeof mapping.parseConfig !== 'object') {
    mapping.parseConfig = {};
  }

  if (typeof mapping.parseConfig.handleMissing !== 'function') {
    mapping.parseConfig.handleMissing = (field, rule) => {
      return rule.required ? `[缺失必填字段: ${field}]` : null;
    };
  }

  return mapping;
}

// 导出模块
module.exports = {
  parseHtmlContent,
  validateMapping,
};
